﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Streambolics.Hp41s
{
    /// <summary>
    ///     An object capable of creating an instruction.
    /// </summary>
    /// <remarks><para>
    ///     An instruction factory is used when parsing source code and
    ///     when interpreting keystrokes.
    /// </para><para>
    ///     When the instruction needs to be parsed from a source code
    ///     file, the Parse() method is called with a tokenizer, and
    ///     the factory should immediately create the instruction.
    /// </para><para>
    ///     When the instruction results from keystrokes, the factory
    ///     should instead instanciate interactive factories to handle
    ///     keyboard input.
    /// </para></remarks>

    public abstract class InstructionFactory
    {
        private string _Name;

        public InstructionFactory (string aName)
        {
            _Name = aName;
        }

        public string Name
        {
            get
            {
                return _Name;
            }
        }

        public override string ToString ()
        {
            return _Name;
        }

        /// <summary>
        ///     Parse the token stream and create the instruction.
        /// </summary>
        /// <param name="aTokenizer">
        ///     The tokenizer containing the source code.
        /// </param>
        /// <returns>
        ///     The parsed instruction
        /// </returns>
        /// <remarks><para>
        ///     At entry, the tokenizer is on the name of the instruction.
        /// </para><para>
        ///     At exit, the tokenizer should be on the last token of the parsed
        ///     instruction.
        /// </para></remarks>

        public abstract Instruction Parse (Tokenizer aTokenizer);

        /// <summary>
        ///     Whether the factory is able to generate an instruction
        ///     immediately. If true, call Create() to create the instruction,
        ///     else call InterpretKey() to interpret a new key.
        /// </summary>

        public virtual bool InstructionAvailable
        {
            get
            {
                return false;
            }
        }

        public virtual Instruction ToInstruction ()
        {
            return null;
        }

        /// <summary>
        ///     Interpret the key and return a new factory being
        ///     the combination of this factory and the key.
        /// </summary>
        /// <param name="aKey">
        ///     The pressed key
        /// </param>
        /// <returns>
        ///     A new factory
        /// </returns>
        /// <remarks><para>
        ///     Factories can be assigned to user actions, therefore a
        ///     factory should always create a new factory after interpreting
        ///     a key, and never simply update an internal state and return
        ///     itself (it is however acceptable to return self if the key
        ///     has no effect or is illegal.)
        /// </para></remarks>

        public virtual InstructionFactory InterpretKey (int aKey)
        {
            return this;
        }

        /// <summary>
        ///     The text to be displayed to the user.
        /// </summary>

        public virtual string Prompt
        {
            get
            {
                return _Name + " __";
            }
        }
    }
}
